﻿/*
 * Copyright (c) 2012, University of Southampton All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of University of Southampton nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.Xml;
using System.Xml.Schema;

namespace LabTroveWebParts
{
    /// <summary>
    /// To add data to a post we need to populate and upload an instance of this dataset class.
    /// </summary>
    public class dataset : IXmlSerializable
    {
        private string _title;
        public string title
        {
            get { return _title; }
            set { _title = value; }
        }

        private List<dataitem> _data;
        public List<dataitem> data
        {
            get { return _data; }
            set { _data = value; }
        }

        /// <summary>
        /// Default constructor
        /// </summary>
        public dataset()
        {
            _data = new List<dataitem>();
        }

        /// <summary>
        /// Instantiates a dataset object with the given title
        /// </summary>
        /// <param name="title">Data item title</param>
        public dataset(string title)
        {
            _title = title;
            _data = new List<dataitem>();
        }


        // XML Serialization Infrastructure
        public void WriteXml(XmlWriter writer)
        {
            writer.WriteElementString("title", "", title);

            writer.WriteStartElement("data");

            foreach (dataitem di in _data)
            {
                writer.WriteStartElement("dataitem");
                writer.WriteAttributeString("type", "", di.type);
                writer.WriteAttributeString("ext", "", di.ext);
                writer.WriteAttributeString("filename", "", di.filename);
                switch (di.type)
                {
                    case "local":
                        writer.WriteAttributeString("main", "", di.main);
                        writer.WriteValue(di.dataNum);
                        break;

                    case "url":
                        writer.WriteString(di.dataUrlString);
                        break;

                    case "inline":
                        writer.WriteAttributeString("main", "", di.main);
                        writer.WriteString(di.b64encData);
                        break;
                }
                writer.WriteEndElement();
            }

            writer.WriteEndElement();
        }


        public void ReadXml(XmlReader Reader)
        {
            Reader.ReadStartElement("dataset");
            _title = Reader.ReadElementContentAsString();

            Reader.ReadStartElement("data");

            while (Reader.HasAttributes)
            {
                string _type = Reader.GetAttribute("type");
                string _ext = Reader.GetAttribute("ext");
                string _filename = Reader.GetAttribute("filename");
                switch (_type)
                {
                    case "url":
                        string _dataUrl = Reader.ReadString();
                        _data.Add(new dataitem(_type, _ext, _filename, _dataUrl));
                        break;
                    case "local":
                        string _sdataNum = Reader.ReadString();
                        int _dataNum = Convert.ToInt32(_sdataNum);
                        _data.Add(new dataitem(_type, _ext, _filename, _dataNum));
                        break;
                    case "inline":
                        string _b64encData = Reader.ReadString();
                        _data.Add(new dataitem(_type, _ext, _filename, _b64encData));
                        break;
                }
                Reader.ReadEndElement();
            }
            Reader.ReadEndElement();
            Reader.ReadEndElement();
        }

        public XmlSchema GetSchema()
        {
            return (null);
        }

    }

    /// <summary>
    /// Class to represent the dataitems in the dataset class.
    /// </summary>
    public class dataitem
    {
        private string _type;
        /// <summary>
        /// type is a string whose values are only "url", or "inline".
        /// </summary>
        [XmlAttribute]
        public string type
        {
            get { return _type; }
            set { _type = value; }
        }

        private string _ext;
        /// <summary>
        ///  ext is a filename extension string, without the dot, e.g. "pdf".
        /// </summary>
        [XmlAttribute]
        public string ext
        {
            get { return _ext; }
            set { _ext = value; }
        }

        private string _main;
        [XmlAttribute]
        public string main
        {
            get { return _main; }
            set { _main = value; }
        }

        private string _filename;
        /// <summary>
        /// the full filename of the data, including extension.
        /// </summary>
        [XmlElementAttribute(IsNullable = false)]
        public string filename
        {
            get { return _filename; }
            set { _filename = value; }
        }

        // Constructors
        /// <summary>
        /// Default constructor
        /// </summary>
        public dataitem()
        {
        }

        /// <summary>
        /// Instantiates a dataitem() for a type of "local".  Requires an integer data ID number.
        /// </summary>
        /// <param name="type">must be "local"</param>
        /// <param name="ext">the extension of the data file name (without dot)</param>
        /// <param name="filename">the full filename of the data file</param>
        /// <param name="dataNum">integer ID number to identify which local data to use</param>
        public dataitem(string type, string ext, string filename, int dataNum)
        {
            _type = type;
            _ext = ext;
            _filename = filename;
            _dataNum = dataNum;
            _main = "1";
        }

        /// <summary>
        /// Instantiates a dataitem() for a type of "url" or "inline".  Requires
        /// the URL of the data item or a base64 encoded string of inline data.
        /// </summary>
        /// <param name="type">must be "url" or "inline"</param>
        /// <param name="ext">the extension of the data file name (without dot)</param>
        /// <param name="filename">the full filename of the data file</param>
        /// <param name="dataString">"url": the full URL of the data file, or
        /// inline: the urlenconde() of the base64-encoded data file</param>
        public dataitem(string type, string ext, string filename, string dataString)
        {
            _type = type;
            _ext = ext;
            _filename = filename;
            if (type == "url")
            {
                _dataUrlString = dataString;
                _main = null;
            }
            if (type == "inline")
            {
                _b64encData = dataString;
                _main = "1";
            }
        }

        private int _dataNum;
        /// <summary>
        /// When specifying type="local", we need an integer reference number.
        /// </summary>
        public int dataNum
        {
            get { return _dataNum; }
            set { _dataNum = value; }
        }

        private string _dataUrlString;
        /// <summary>
        /// When specifying type="url" this string is the value of the dataitem URL.
        /// NB: LabTrove does not copy the item, it only stores its URL.
        /// </summary>
        public string dataUrlString
        {
            get { return _dataUrlString; }
            set { _dataUrlString = value; }
        }

        private string _b64encData;
        /// <summary>
        /// When type="inline" we specify this string, which contains the urlencode() 
        /// of the base64-encoded file whose name is specified by the filename parameter.
        /// </summary>
        public string b64encData
        {
            get { return _b64encData; }
            set { _b64encData = value; }
        }
    }
}
